package com.cetc.sdp.kmga.cs.device;

import com.cetc.sdp.kmga.cs.util.Tool;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @description:
 * @author： DengQiang
 * @date: 2017/8/29 13:42
 */
public class DeviceExpCheck implements Serializable {

    private List<DeviceExpCode> deviceExpCodes; //设备异常规则码表

    private Map<String, List<DeviceExpCode>> codeTypeMap; //设备异常归类

    private Map<Integer, DeviceExpCode> expCodeMap; //设备异常类型码表映射

    public DeviceExpCheck(List<DeviceExpCode> deviceExpCodes) {
        this.deviceExpCodes = deviceExpCodes;
        this.codeTypeMap = new HashMap<>();
        this.expCodeMap = new HashMap<>();
        this.deviceExpCodes.forEach(code -> {
            this.codeTypeMap.computeIfAbsent(code.getType(), k -> new ArrayList<>()).add(code);
            this.expCodeMap.put(code.getExcpCode(), code);
        });
        this.codeTypeMap.entrySet().forEach(e -> e.getValue().sort((o1, o2) -> o2.getLevel() - o1.getLevel()));
    }

    public List<DeviceExpEvent> check(StateLog log) {

        List<DeviceExpEvent> expEvents = new ArrayList<>();

        for (Map.Entry<String, List<DeviceExpCode>> entry : codeTypeMap.entrySet()) {
            String type = entry.getKey();
            List<DeviceExpCode> codes = entry.getValue();
            switch (type) {
                case "CPU使用":
                    DeviceExpEvent expEvent = check(log.getCpuUse()/100.0, codes, type, log);
                    if (expEvent != null) {
                        expEvents.add(expEvent);
                    }
                    break;
                case "内存使用":
                    long total = log.getMemTotal();
                    long userd = log.getMemUse();
                    double p = userd * 1.0/total;
                    expEvent = check(p, codes, type, log);
                    if (expEvent != null) {
                        expEvents.add(expEvent);
                    }
                    break;
                case "IO":

                    break;
                case "磁盘空间使用":
                    total = log.getDiskTotal();
                    userd = log.getDiskUse();
                    p = userd * 1.0/total;
                    expEvent = check(p, codes, type, log);
                    if (expEvent != null) {
                        expEvents.add(expEvent);
                    }
                    break;
                case "负载":
                    break;
                default:
            }
        }
        return expEvents;
    }

    public DeviceExpCode getOfflineExpCode() {
        return this.codeTypeMap.get("离线").get(0);
    }

    public DeviceExpCode getExpCode(int code) {
        return this.expCodeMap.get(code);
    }

    private DeviceExpEvent check(double value, List<DeviceExpCode> codes, String type, StateLog log) {
        for (DeviceExpCode expCode : codes) {
            if (cmp(expCode.getCmpType(), value, expCode.getValue())) {
                DeviceExpEvent tmpExpEvent = new DeviceExpEvent();
                String device_id = log.getDevId();
                String time = LocalDateTime.now().format(Tool.DEFAULT_TIME_FORMATTER);
                tmpExpEvent.setExcpCode(expCode.getExcpCode());
                tmpExpEvent.setDeviceId(device_id);
                tmpExpEvent.setStartTime(time);
                tmpExpEvent.setLevel(expCode.getLevel());
                return tmpExpEvent;
            }
        }
        return null;
    }

    private boolean cmp(int cmpType, double value, double threshold) {
        if (cmpType == 0) {
            if (value >= threshold) {
                return true;
            }
        } else if (cmpType == 1) {
            if (value <= threshold) {
                return true;
            }
        }
        return false;
    }
}
